
package aca;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SimpleChecker {

        private ArrayList<String> allFiles = new ArrayList<String>();
        private ArrayList<String> logFile = new ArrayList<String>();;
        
        public void runChecker (String path, String criterios) throws Exception{
                logFile = new ArrayList<String>();
                getAllFiles(new File(path));            
                for (int i = 0; i < allFiles.size(); i++) {
                        callChecker(path, allFiles.get(i), criterios);
                 }
                
                System.out.println(logFile.size());
        }
        
        public void getAllFiles(File file) {
                if(file.isFile() && file.getAbsolutePath().endsWith(".java")){
                      allFiles.add(file.getAbsolutePath());
                }else{
                        if (file.isDirectory()) {
                                File[] listOfFiles = file.listFiles();
                                if(listOfFiles!=null) {
                        for (int i = 0; i < listOfFiles.length; i++)
                                getAllFiles(listOfFiles[i]);
                                }
                        }
                }
        }
        
        public void callChecker(String path, String fileToCheck, String criterios) throws IOException, ParserConfigurationException, SAXException, InterruptedException {
                Process proc = Runtime.getRuntime().exec("java -jar ./checkstyle-5.5/checkstyle-5.5-all.jar \\ -c " +
                                criterios + " -f xml -o ./logs/checkstyle_errors.xml " +
                                fileToCheck);
                proc.waitFor();
                proc.getOutputStream().close();
        logFile.addAll(readXML(fileToCheck));
        
        for (String error : logFile) {
                        System.out.println(error);
                }
        
        File file = new File(path);
        String fileName = file.getName();
        File logStudent = new File("./web-app/feedback/"+fileName+".txt");
        if (!(logStudent.exists()))
                logStudent.createNewFile();
        
        System.out.println(logStudent.exists());
        PrintStream out = null;
        try {
            out = new PrintStream(new FileOutputStream(logStudent));
            for (String log : logFile) {
                out.print(log +"\n");
                        }
        }
        finally {
            if (out != null) out.close();
        }
        }
        
        public ArrayList<String> readXML(String resourceFile) throws ParserConfigurationException, SAXException, IOException {
                String logName =  "./logs/checkstyle_errors.xml";
                File fXmlFile = new File(logName);

                DocumentBuilderFactory dbFactory = DocumentBuilderFactory
                        .newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(fXmlFile);
                doc.getDocumentElement().normalize();
                
                NodeList nList = doc.getElementsByTagName("error");

                ArrayList<String> errorsMap = new ArrayList<String>();
                for (int i = 1; i < nList.getLength(); i++) {

                    Node node = nList.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {

                        Element errorNode = (Element) node;
                        
                        String errorLog =  resourceFile + " <startshere> line:" + errorNode.getAttribute("line") + " message: " + 
                                                                errorNode.getAttribute("message");
                        
                        errorsMap.add(errorLog);
                    }
                }
             
           return errorsMap;
        }
        
        public void descompressAllFile(String activityPath) throws IOException{
                File activities = new File(activityPath);
                File[] listOfFiles = activities.listFiles();
                if (listOfFiles==null)
                        return;
                for (int i = 0; i < listOfFiles.length; i++) {
                        descompressAllFile(listOfFiles[i].toString());
                        if (listOfFiles[i].getAbsolutePath().endsWith(".zip")) {
                                descompressFile(listOfFiles[i].getAbsolutePath(), activityPath);
                        }
                }
        }
        
        public void descompressFile(String zipName, String destDirectory) throws IOException{
                
                @SuppressWarnings("resource")
                ZipFile zipFile = new ZipFile(zipName);
                Enumeration<? extends ZipEntry> files = zipFile.entries();
            File f = null;
            FileOutputStream fos = null;
            
            while (files.hasMoreElements()) {
              try {
                ZipEntry entry = (ZipEntry) files.nextElement();
                InputStream eis = zipFile.getInputStream(entry);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
          
                f = new File(destDirectory + File.separator + entry.getName());
                
                if (entry.isDirectory()) {
                  f.mkdirs();
                  continue;
                } else {
                  f.getParentFile().mkdirs();
                  f.createNewFile();
                }
                
                fos = new FileOutputStream(f);
          
                while ((bytesRead = eis.read(buffer)) != -1) {
                  fos.write(buffer, 0, bytesRead);
                }
              } catch (IOException e) {
                e.printStackTrace();
                continue;
              } finally {
                if (fos != null) {
                  try {
                    fos.close();
                  } catch (IOException e) {
                    // ignore
                  }
                }
              }
            }
        }
        
        public void runCheckerForAllActivities(String activityPath, String criterios) throws Exception{
                descompressAllFile(activityPath);
                File directory = new File(activityPath);
                ArrayList<String> activitiesPaths = getAllDirectories(directory);
                for (String path : activitiesPaths) {
                        runChecker(path, criterios);
                }
        }
        
        public ArrayList<String> getAllDirectories(File file) {
                ArrayList<String> activitiesDirectories = new ArrayList<String>();
                File[] listOfFiles = file.listFiles();
                for (int i = 0; i < listOfFiles.length; i++) {
                        if (listOfFiles[i].isDirectory()) {
                                activitiesDirectories.add(listOfFiles[i].getAbsolutePath());
                        }
                }
                
                return activitiesDirectories;
        }

        public static void main(String[] args) throws Exception {
                SimpleChecker s = new SimpleChecker();
                s.runCheckerForAllActivities("C:\\Users\\Public\\Documents\\p1\\","./criterios/Criterios_Lab_5.xml");
        }
}